﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using System.Threading;

using alib.Debugging;
using alib.Enumerable;
using alib.String;
//using alib.Unsafe;
using alib.Collections.ReadOnly;
using alib.Concurrency;
using alib.Tally;

namespace agree
{
	[DebuggerDisplay("{ToString(),nq}")]
	public partial class GenControl : ChartControl<GenControl, CoverageMap>
	{
		void _debug_show_gen_input(GenerationInput input)
		{
			if (cconfig.Job.Verbose == 0)
				return;
			Console.Out.WriteLineColor("$darkyellow ----------- input ---------------");
			foreach (var ee in input.RelSlots.OrderBy(r => r[input.mrsm.IndexPath].TypeNameOrStringValue))
				Console.WriteLine("{0,2} {1}", ee[input.mrsm.IndexPath].TypeNameOrStringValue, ee.ToString());
			Console.WriteLine();

			//foreach (var ee in input.variables)
			//{
			//	Console.WriteLine("{0}", ee.SkolemString);
			//	foreach (var xxx in ee.OrderBy(rx => rx.rel is agree.Mrs.Relation ? ((agree.Mrs.Relation)rx.rel).index : -1))
			//	{
			//		Console.WriteLine("\t{0,-8} {1}", xxx.Feature, xxx.rel is agree.Mrs.Relation ? ((agree.Mrs.Relation)xxx.rel).ToString3() : "-mrs-");
			//	}
			//}
			Console.WriteLine();
		}
	};

	public static class ext
	{
#if false
		public static String Display(GenControl ctrl, String msg, IChartObj<CoverageMap> old, Tfs newtfs, CoverageMap cm_new, ulong computed = 0xffffffffffffffff)
		{
			String s = "";

			s += "$cyan " + _ctr_16(ctrl.input, msg ?? "") + "$ \r\n";

			//s += "$darkred " + new StackTrace(2, true).GetFrame(0).ToString() + "$ ";

			if (old != null)
			{
				s += _obj_disp1(ctrl, old, old.Tfs, old.ProximalContext);
			}
			s += _obj_disp1(ctrl, null, newtfs, cm_new);

			foreach (var ri in ctrl.input.Rels)
				s += String.Format("--------------- ");
			s += Environment.NewLine;

			if (old != null)
			{
				s += _obj_disp2(ctrl, "old daughter", old, old.Tfs, old.ProximalContext);
			}
			s += _obj_disp2(ctrl, "new mother", null, newtfs, cm_new, computed);
			return s;
		}
#endif
		static String _obj_disp1(GenControl ctrl, IChartObj<CoverageMap> old, Tfs tfs, CoverageMap cm)
		{
			String s = "";

			if (old != null)
			{
				s += String.Format("{0:X6} {1} {2} ",
					 old.Id,
					 old.GetType().Name,
					 old.ChartLicense.Name);
			}
			s += tfs.ToString() + "\r\n";

#if MRS_ISNT_CHEAP
			if (tfs.Mrs != null)
				s += tfs.Mrs.ToString();
			else
				s += "no mrs\r\n";
#endif
			return s;
		}

#if false
		static String _obj_disp2(GenControl ctrl, String msg, IChartObj<CoverageMap> old, Tfs tfs, CoverageMap cm, ulong computed = 0xffffffffffffffff)
		{
			String s = msg + "\r\n";

			String tmp;
			for (int i = 0; i < ctrl.rel_slots.Length; i++)
			{
				var rel_slot = ctrl.rel_slots[i];

				String j = rel_slot[ctrl.fsu.mrsm.ifeat_pred].TypeNameOrStringValue;
				if (j.Length > 14)
					j = j.Remove(14);
				tmp = String.Format("{0,-15}", j);
				if ((ctrl.rel_varbits[i] & cm.covered_eps) != 0)
				{
					tmp = "$yellow " + tmp + "$";
					//Debug.Assert(cm_new.SetBits.Contains(rel.index));
				}
				else
				{
					tmp = "$darkyellow " + tmp + "$";
					//Debug.Assert(cm_new.UnsetBits.Contains(rel.index));
				}
				tmp += " ";
				s += tmp;
			}
			s += Environment.NewLine;
			s += _var_bits(ctrl, cm.access_vars) + Environment.NewLine;
			if (computed != 0xffffffffffffffff)
				s += _var_bits(ctrl, computed) + Environment.NewLine;
			return s;
		}

		static String _var_bits(GenControl ctrl, ulong ul)
		{
			String s = "", tmp;
			for (int i = 0; i < ctrl.rel_slots.Length; i++)
			{
				var rel_slot = ctrl.rel_slots[i];

				//fix later

				//int c = 0;
				//foreach (var v in rel.Variables)
				//{
				//	tmp = v.SkolemString;
				//	c += tmp.Length + 1;
				//	if (v.CheckVarBits(ul))
				//		tmp = "$green " + tmp + "$";
				//	else
				//		tmp = "$darkgreen " + tmp + "$";
				//	tmp += " ";
				//	s += tmp;
				//}
				//s += new String(' ', 16 - c);
			}
			return s;
		}
#endif
		static String _ctr_16(GenerationInput input, String txt)
		{
			txt = " " + txt + " ";
			int j = (input.RelSlots.Length * 16) - txt.Length;
			j = Math.Max(j, 0);
			txt = new String('=', j / 2) + txt;
			return txt.PadRight(input.RelSlots.Length * 16 - 1, '=');
		}

#if false
			//s += input_mrs.ToString() + "\r\n";
			s += ctrl.VariableMap(accessible, true) + "\r\n";
			s += "$yellow ----- independent MRS from new TFS ----$ \r\n";
			if (tfs.Mrs != null)
				s += tfs.Mrs.ToString() + "\r\n";
			else
				s += "(none)\r\n";
			s += "$yellow ---- covered EPs ----$ \r\n";
			var _z = bits;
			s += Enumerable.Range(0, input_mrs.RelsCount).Select(j => (((ulong)1 << j) & _z) != 0 ? String.Format("{0,2}", j) : "  ").StringJoin(" ") + "\r\n";
			s += "$yellow ---- not-covered EPs ----$ \r\n";
			s += Enumerable.Range(0, input_mrs.RelsCount).Select(j => (((ulong)1 << j) & _z) == 0 ? String.Format("{0,2}", j) : "  ").StringJoin(" ") + "\r\n";
			s += "$yellow ---- previously accessible ----$ \r\n";
			s += input_mrs.DisplayVariables(prev_access) + "\r\n";
			s += "$yellow ---- previously inaccessible ----$ \r\n";
			s += input_mrs.DisplayVariables(inaccessibile) + "\r\n";
			s += "$yellow ---- computed accessible ----$ \r\n";
			s += input_mrs.DisplayVariables(ul) + "\r\n";
			//s += "$cyan =========================================\r\n";
#endif
	};

	public partial struct CoverageMap : IProximalContext<CoverageMap>
	{
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public IEnumerable<int> SetBits
		{
			get
			{
				int c = input.RelSlots.Length;
				ulong msk = 1;
				for (int i = 0; i < c; i++)
				{
					if ((covered_eps & msk) != 0)
						yield return i;
					msk <<= 1;
				}
			}
		}

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public IEnumerable<int> UnsetBits
		{
			get
			{
				int c = input.RelSlots.Length;
				ulong msk = 1;
				for (int i = 0; i < c; i++)
				{
					if ((covered_eps & msk) == 0)
						yield return i;
					msk <<= 1;
				}
			}
		}

		//[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
		//public String[] _dbg_view { get { return _dbg_view_helper.ToArray(); } }

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		IEnumerable<String> _dbg_view_helper
		{
			get
			{
				int c = input.RelSlots.Length;
				ulong msk = 1;
				for (int i = 0; i < c; i++)
				{
					if ((covered_eps & msk) != 0)
					{
						yield return String.Format("{0}: {1}", i.ToString(), input.RelSlots[i][input.mrsm.ifeat_lbl].TypeNameOrStringValue);
					}
					msk <<= 1;
				}
			}
		}
	};
}
